#include "Goomba.h"
#include "Method.h"
#include "PlayState.h"
Goomba::Goomba(float posX, float posY, float width, float height, Resources* res, int number, int depth)
:GameObject(posX, posY, width, height, res, number, depth)
{
	_sprite = new Sprite(_resources->Goomba, 11, 11, 0.1f);
	_sprite->Next(1);

	if (rand() % 2 == 1)
		_direction = -1;		// left
	else
		_direction = 1;			// right

	_vel_x = _direction * GOOMBA_VX;
	_vel_y = 0;
	_acc_y = GRAVITY;

	_time_del = 0;

	_id = ID::ID_Goomba;
	_state = GOOMBA_STATE::GOOMBA_NORMAL;
	_old_rect = _rect;

	_isStatic = false;
}

Goomba::~Goomba()
{

}

void Goomba::Update(float time, QNode* &Tree)
{
	vector<GameObject*>  listObj, stListObj;

	Method::GetObjectInViewport(_rect, Tree, listObj, stListObj);

	Move(time, stListObj);

	UpdateAnimation(time);

	// When goomba die, sprite is lose now
	// Then some second, it lost
	if (_state == GOOMBA_STATE::GOOMBA_DIE)
		_time_del += 1;

	// Set isAlive
	if (_time_del > 100 || _pos_y < 0)
		_isAlive = false;

	
}

void Goomba::Render(LPD3DXSPRITE spriteHandler, Viewport* viewport)
{
	if (_state == GOOMBA_STATE::GOOMBA_FALL)
	{
		if (_direction == 1)
			_sprite->Render(spriteHandler, _pos_x, _pos_y, 1, 1, 3.14f, viewport);
		else
			_sprite->Render(spriteHandler, _pos_x, _pos_y, 1, 1, 3.14f, viewport);
	}
	else
	{
		if (_direction == 1)
			_sprite->Render(spriteHandler, _pos_x, _pos_y, false, viewport);
		else
			_sprite->Render(spriteHandler, _pos_x, _pos_y, true, viewport);
	}
}

void Goomba::UpdateAnimation(float time)
{
	switch (_state)
	{
	case GOOMBA_STATE::GOOMBA_NORMAL:
		_sprite->Next(1, 10, time);
		break;
	case GOOMBA_STATE::GOOMBA_DIE:
		_sprite->Next(0);
		break;
	default:
		break;
	}
}

void Goomba::Move(float time, vector<GameObject*> list)
{
	if (_state == GOOMBA_STATE::GOOMBA_DIE)
		return;


	// Save old position
	_old_x = _pos_x;
	_old_y = _pos_y;

	// Move X
	_pos_x += _vel_x * time;

	// Move Y
	_vel_y += _acc_y * time;

	_pos_y -= _vel_y * time + 0.5f * _acc_y * time * time;
	_old_rect = _rect;
	ResetRect();

	if (_state != GOOMBA_STATE::GOOMBA_NORMAL) return;

	// List  Object have collision with this
	vector<GameObject*> listCollision;

	int n = list.size();
	for (int i = 0; i < n; i++)
	{
		if (list[i]->ID() != this->_id)
		{
			float CollisionTime;
			// Check collision and get direction collision
			DirCollision dir = Method::IsCollision(this, list[i], CollisionTime);

			// Not collision
			if (dir != DirCollision::NONE)
			{
				list[i]->TimeCollision = CollisionTime;
				listCollision.push_back(list[i]);
			}
		}
	}

	// Sort List Objects have collision by TimeCollision
	// Object have TimeCollision minimum will happen collision first.
	std::sort(listCollision.begin(), listCollision.end(), Method::MinDistance);

	for (int i = 0; i < listCollision.size(); i++)
	{
		float CollisionTime;
		DirCollision dir = Method::IsCollision(this, listCollision[i], CollisionTime);

		// Have collision
		switch (listCollision[i]->ID())
		{
		case ID::ID_Brick:
			// If Brick is breaking, don't check collision
			if (listCollision[i]->GetState() == BRICK_STATE::BRICK_BREAK) break;

			if (dir == DirCollision::LEFT || dir == DirCollision::RIGHT)
			{
				_pos_x = _old_x + (_pos_x - _old_x) * CollisionTime;
				ResetRect();
				_direction *= -1;
				_vel_x *= -1;
			}
			else if (dir == DirCollision::BOTTOM)
			{
				if (listCollision[i]->GetState() == BRICK_STATE::BRICK_MOVEUP
					|| listCollision[i]->GetState() == BRICK_STATE::BRICK_BREAK)
				{
					ChangeState(GOOMBA_STATE::GOOMBA_FALL);
					_pos_y = (int)(_old_y + (_pos_y - _old_y) * CollisionTime + 20);
				}
				else
				{
					_pos_y = (int)(_old_y + (_pos_y - _old_y) * CollisionTime + 2);
					ResetRect();
					_vel_y = 0;
				}
			
			}
			break;
		case ID::ID_Land:
		case ID::ID_StoneA:
		case ID::ID_StoneB:
		case ID::ID_Pipe1:
		case ID::ID_Pipe2:
		case ID::ID_Pipe3:
		case ID::ID_PipeSpecial:
		case ID::ID_QBrick:
			if (dir == DirCollision::LEFT || dir == DirCollision::RIGHT)
			{
				_pos_x = _old_x + (_pos_x - _old_x) * CollisionTime;
				ResetRect();
				_direction *= -1;
				_vel_x *= -1;
			}
			else if (dir == DirCollision::BOTTOM)
			{
				_pos_y = (int)(_old_y + (_pos_y - _old_y) * CollisionTime + 2);
				ResetRect();
				_vel_y = 0;
			}
			break;
		default:
			break;
		}
	}
}

void Goomba::ChangeState(char state)
{
	_state = state;
	if (_state == GOOMBA_STATE::GOOMBA_DIE)
		_vel_x = _acc_x = 0;
	else
	{
		_vel_x = _acc_x = 0;
		_vel_y = -GOOMBA_VY;
		_acc_y = GRAVITY;
	}
}